package com.weirq.db;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;

import com.weirq.util.BaseUtils;
import com.weirq.util.DateUtil;
import com.weirq.util.FileUtils;
import com.weirq.util.SiteUrl;
import com.weirq.vo.FileSystemVo;
import com.weirq.vo.Menu;

/**
 * 
 * @author pc-Haitao
 * @ClassName:HdfsDB 声明几种文件的操作方法
 * @Version 版本
 * @Modifiedby 修改人
 * @Copyright 公司名称
 * @date 2016年8月18日下午4:52:22
 */
public class HdfsDB {
	// 定义一个文件类型的数组
	private static String[] suf = { "csv", "txt", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "jpg", "png", "gif" };
	private static String[] txt = { "txt", "doc", "docx", "xls", "xlsx", "ppt", "pptx" };
	private static String[] img = { "jpg", "png", "gif" };
	static FileSystem fs;// 声明文件系统类对象
	static Configuration conf;// 声明配置类对象

	private static class HdfsDBInstance {
		private static final HdfsDB instance = new HdfsDB();
	}

	public static HdfsDB getInstance() {
		return HdfsDBInstance.instance;
	}

	private HdfsDB() {
		conf = new Configuration();
		conf.set("fs.defaultFS", SiteUrl.readUrl("hdfs"));
		try {
			fs = FileSystem.get(conf);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 以流形式上传文件
	 * 
	 * @param in
	 * @param dir
	 * @throws Exception
	 */
	public void upload(InputStream in, String dir) throws Exception {
		OutputStream out = fs.create(new Path(dir), new Progressable() {
			@Override
			public void progress() {
			}
		});
		IOUtils.copyBytes(in, out, 4096, true);
	}

	/**
	 * 下载文件
	 * 
	 * @param path
	 * @param local
	 * @throws Exception
	 */
	public void downLoad(String path, HttpServletResponse response, String name) throws Exception {
		String str = new String(name.getBytes(), "ISO8859-1");// 重新用utf-8编码*/
		FSDataInputStream in = fs.open(new Path(path));
		// 设置响应头，控制浏览器下载该文件
		response.setHeader("content-disposition", "attachment;filename=" + str);
		// 创建输出流
		OutputStream out = response.getOutputStream();
		IOUtils.copyBytes(in, out, 4096, true);
	}

	/**
	 * 重命名文件
	 * 
	 * @param src
	 * @param dst
	 * @throws Exception
	 */
	public void rename(String src, String dst) throws Exception {
		fs.rename(new Path(src), new Path(dst));// 重命名方法
	}

	/**
	 * 创建文件夹
	 * 
	 * @param dir
	 * @throws Exception
	 */
	public void mkdir(String dir) throws Exception {
		if (!fs.exists(new Path(dir))) {
			fs.mkdirs(new Path(dir));// 创建文件夹方法
		}
	}

	/**
	 * 删除文件及文件夹
	 * 
	 * @param name
	 * @throws Exception
	 */
	public void delete(String name) throws Exception {
		fs.delete(new Path(name), true);// 删除文件夹方法
	}

	/**
	 * 查询文件夹 根据上层目录名 查询该目录下所有文件及文件夹
	 * 
	 * @param dir
	 * @return
	 * @throws Exception
	 */
	public List<FileSystemVo> queryAll(String dir) throws Exception {
		FileStatus[] files = fs.listStatus(new Path(dir));// 查询指定文件夹方法
		List<FileSystemVo> fileVos = new ArrayList<FileSystemVo>();
		FileSystemVo f = null;// 声明文件输出实体类对象
		for (int i = 0; i < files.length; i++) {
			f = new FileSystemVo();
			if (files[i].isDirectory()) {
				f.setName((files[i].getPath().getName()));
				f.setType("D");// 设置文件类型 "D"为文件夹 "F"为文件
				f.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));
				f.setNamep(files[i].getPath().getName());
			} else if (files[i].isFile()) {
				f.setName(files[i].getPath().getName());// 设置文件名
				f.setType("F");
				f.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));// 设置日期
				f.setSize(BaseUtils.FormetFileSize(files[i].getLen()));// 设置文件大小
				f.setNamep(f.getName().substring(0, f.getName().lastIndexOf(".")));
				String s = FileUtils.getFileSufix(f.getName());
				for (int j = 0; j < suf.length; j++) {
					if (s.equals(suf[j])) {// 匹配此文件是哪种类型的文件
						f.setViewflag(s);// 匹配到类型文件
						break;
					}
				}
			}
			fileVos.add(f);
		}
		return fileVos;
	}

	/**
	 * 移动或复制文件
	 * 
	 * @param path
	 *            文件路径数组 包含原路径和新路径
	 * @param dst
	 *            文件名
	 * @param src
	 *            true 移动文件;false 复制文件
	 * @throws Exception
	 */
	public void copy(String[] path, String dst, boolean src) throws Exception {
		Path[] paths = new Path[path.length];// 路径长度
		for (int i = 0; i < path.length; i++) {
			paths[i] = new Path(path[i]);
		}
		FileUtil.copy(fs, paths, fs, new Path(dst), src, true, conf);// 调用文件工具类的复制方法
	}

	public List<Menu> tree(String dir) throws Exception {
		FileStatus[] files = fs.listStatus(new Path(dir));// 查看文件夹
		List<Menu> menus = new ArrayList<Menu>();
		for (int i = 0; i < files.length; i++) {
			if (files[i].isDirectory()) {// 判断是否是文件夹
				menus.add(new Menu(files[i].getPath().toString(), files[i].getPath().getName()));
			}
		}
		return menus;
	}

	/**
	 * 搜索文件
	 * 
	 * @param name
	 * @param searchName
	 * @return
	 * @throws Exception
	 */
	public List<FileSystemVo> queryByName(String dir, String searchName) throws Exception {
		FileStatus[] files = fs.listStatus(new Path(dir));// 查询文件夹方法
		List<FileSystemVo> fileVos = new ArrayList<FileSystemVo>();
		FileSystemVo fs = null;// 声明文件输出实体类对象
		for (int i = 0; i < files.length; i++) {
			fs = new FileSystemVo();
			if (files[i].isDirectory()) {// 是否是文件夹
				if ((files[i].getPath().getName()).contains(searchName)) {
					fs.setName((files[i].getPath().getName()));
					fs.setType("D");// 设置文件类型 "D"为文件夹 "F"为文件
					fs.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));
					fileVos.addAll(queryByName(files[i].getPath().toString(), searchName));
				} else {
					fileVos.addAll(queryByName(files[i].getPath().toString(), searchName));// 递归执行此方法 并将查找结果加到list数组上
				}
			} else if (files[i].isFile()) {// 是否是文件
				if (files[i].getPath().getName().contains(searchName)) {
					fs.setName(files[i].getPath().getName());// 设置文件名
					fs.setType("F");
					fs.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));// 设置日期
					fs.setSize(BaseUtils.FormetFileSize(files[i].getLen()));// 设置文件大小
					String s = FileUtils.getFileSufix(fs.getName());
					for (int j = 0; j < suf.length; j++) {
						if (s.equals(suf[j])) {// 匹配此文件是哪种类型的文件
							fs.setViewflag(s);// 匹配到类型文件
							break;
						}
					}
				}
			}
			fileVos.add(fs);
		}
		return fileVos;
	}

	/**
	 * 显示文件下所有文档
	 * 
	 * @param dir
	 * @return
	 * @throws Exception
	 */
	public List<FileSystemVo> queryAlltxt(String dir, String path) throws Exception {
		FileStatus[] files = fs.listStatus(new Path(dir));// 查询文件夹方法
		List<FileSystemVo> fileVos = new ArrayList<FileSystemVo>();
		FileSystemVo fs = null;// 声明文件输出实体类对象
		for (int i = 0; i < files.length; i++) {
			fs = new FileSystemVo();
			if (files[i].isDirectory()) {// 是否是文件夹
				fileVos.addAll(queryAlltxt(files[i].getPath().toString(), dir + "/" + files[i].getPath().getName()));
			} else if (files[i].isFile()) {// 是否是文件
				String name = files[i].getPath().getName();
				for (int k = 0; k < txt.length; k++) {
					if (name.endsWith(txt[k]) == true) {
						fs.setName(name);// 设置文件名
						fs.setType("F");// 设置文件类型 "F"为文件
						fs.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));// 设置日期
						fs.setSize(BaseUtils.FormetFileSize(files[i].getLen()));// 设置文件大小
						fs.setViewflag(txt[k]);// 匹配到类型文件
						fs.setNamep(path);// 设置所在目录
						fileVos.add(fs);
					}
				}
			}
		}
		return fileVos;
	}

	/**
	 * 显示文件夹下所有图片
	 * 
	 * @param dir
	 * @return
	 * @throws Exception
	 */
	public List<FileSystemVo> queryAllimg(String dir, String path) throws Exception {
		FileStatus[] files = fs.listStatus(new Path(dir));// 查询文件夹方法
		List<FileSystemVo> fileVos = new ArrayList<FileSystemVo>();
		FileSystemVo fs = null;// 声明文件输出实体类对象
		for (int i = 0; i < files.length; i++) {
			fs = new FileSystemVo();
			if (files[i].isDirectory()) {// 是否是文件夹
				fileVos.addAll(queryAllimg(files[i].getPath().toString(), dir + "/" + files[i].getPath().getName()));
			} else if (files[i].isFile()) {// 是否是文件
				String name = files[i].getPath().getName();
				for (int k = 0; k < img.length; k++) {
					if (name.endsWith(img[k]) == true) {
						fs.setName(name);// 设置文件名
						fs.setType("F");// 设置文件类型 "F"为文件
						fs.setDate(DateUtil.longToString("yyyy-MM-dd HH:mm", files[i].getModificationTime()));// 设置日期
						fs.setSize(BaseUtils.FormetFileSize(files[i].getLen()));// 设置文件大小
						fs.setViewflag(img[k]);// 匹配到类型文件
						fs.setNamep(path);// 设置所在目录
						fileVos.add(fs);
					}
				}
			}
		}
		return fileVos;
	}
}
